package model;

import java.awt.Color;
import java.awt.Point;

import common.Direction;

/**
 * Hold the details of an individual snake.
 * @author Robert Wilson
 * @version 1.0
 */
public class Snake implements Runnable, Drawable {

	//hold which way the 
	private Direction currentDirection;
	
	private Point head;//thread confined
	private Point[] body;//thread confined
	private int segmentSize = 10;
	private int sleepTime = 1000;
	private int headPos = 0;//thread confined
	/** This is the length that the snake is */
	private int length = 1;//thread confined
	private Color color;
	/** Flag to indicate if a request has been made to stop this snake.*/
	private volatile boolean keepGoing = true;//volatile
	
	public Snake(Direction direction, Color color) {
		currentDirection = direction;
		head = new Point(100, 100);
		body = new Point[length];
		body[0] = head;
		this.color = color;
	}

	/** Let this snake know he has just eaten something */
	public void eaten() {
		//increment the length
		length++;
		
		//create a new body equal to the new length
		Point[] newBody = new Point[length];
		
		/* copy the current body into the new body*/
		System.arraycopy(body, 0, newBody, 0, body.length);
		
		/* duplicate the head's current position and add it into the body array at the end */
		newBody[newBody.length-1] = new Point((int)head.getX(), (int)head.getY());
		
		/* Update the existing array with the new one*/
		body = newBody;
	}
	
	/** Update which way the snake is going. */
	public void changeDirection(Direction dir) {
		currentDirection = dir;
	}
	
	/** Tell the snake to stop going. */
	public void stop() {
		keepGoing = false;
	}
	
	/**
	 * Move the snake by updating the head and removing the tail, kinda like moving the tail and
	 * placing it as the head
	 */
	public void run() {
		while (keepGoing) {
			calcHeadPos();
			move();
			rest();
		}
	}
	
	/** Make the snake pause */
	private void rest() {
		System.out.println(this);
		try {
			System.out.println("snake going to sleep");
			Thread.sleep(sleepTime);
		} catch (InterruptedException ex) {
			Thread.currentThread().interrupt();
		}
		System.out.println("snake waking up");
	}

	/** Move the body by moving the head along one */
	private void move() {
		headPos++;
		if (headPos == body.length) {
			headPos = 0;
		} 
		body[headPos] = head;
	}

	/** Move the head based on the size of the head and the current direction of the snake */
	private void calcHeadPos() {
		int x = (int) head.getX();
		int y = (int) head.getY();
		switch (currentDirection) {		
			case NORTH : head = new Point(x, y - segmentSize); break;
			case SOUTH : head = new Point(x, y + segmentSize); break;
			case EAST : head = new Point(x - segmentSize, y); break;
			case WEST : head = new Point(x + segmentSize, y); break;
		}
	}
	
	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Snake: Direction " + currentDirection + "\n");
		builder.append("headPos = " + headPos + "\n");
		builder.append("Head at " + head + "\n");
		for (int i=1; i < body.length; i++) {
			builder.append("Body " + i + " at " + body[i] + "\n");
		}
		
		return builder.toString();
		
	}
	
	/** {@inheritDoc} */
	public Point[] getLocations() {
		return body.clone();
	}
	
	public static void main(String[] args) {
		Snake snake = new Snake(Direction.NORTH, Color.BLACK);
		Thread snakeThread = new Thread(snake);
		System.out.println("snake started");
		snakeThread.start();
		
		System.out.println("sleeping in main for 3 seconds");
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("changing direction to EAST");
		snake.changeDirection(Direction.EAST);
		
		System.out.println("sleeping in main for 3 seconds");
		try {
			Thread.sleep(3000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("EATING!!!");
		snake.eaten();
		snake.eaten();
		snake.eaten();
		snake.eaten();
		snake.eaten();
		snake.eaten();
		snake.eaten();
		snake.eaten();
		
		System.out.println("sleeping in main for 10 seconds");
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		snake.stop();
		snakeThread = null;
		snake = null;
		System.out.println("Finished");
	}

	/** {@inheritDoc} */
	public Color getColor() {
		return color;
	}

	public Direction getDirection() {
		return currentDirection;
	}

	
}
